#ifndef _ROOM_BASE_H_
#define _ROOM_BASE_H_

#include "Define.h"
#include "Header.h"
#include <map>
#include <set>
#include <string>
#include "msg_common.h"

#define INVALID_SEAT (-1) 

class CPlayerBase;
class CRoomBase
{
    friend class CHall;

public:
	enum ERoomState
	{
		E_RoomState_Idle,			// 空房间
		E_RoomState_Waiting,		// 等待游戏开始
		E_RoomState_Gaming,			// 游戏中
	};
    
    struct FriendData
    {
        u64 _creater;
        s32 _maxRound;
        s32 _curRound;
        s32 _number;
        std::string _cfg; // json
        s16 _dismissState; // -1:noone ask dismiss 0:begin dismiss >1:agree or not count
        std::set<s32> _waitDismissUser; // seatno
        s16 _dismissCount;
        u64 _battleId;
        u64 _createTime; // 房间创建时间, 超时后自动销毁
        u64 _dismissEndTime;    //解散到期时间
    };

	CRoomBase(s32 id);
	virtual ~CRoomBase();

	virtual void OnPlayerEnter(CPlayerBase &player){}
	virtual void OnBeforePlayerLeave(CPlayerBase &player){}
	virtual void OnPlayerLeave(CPlayerBase &player, s32 seat=INVALID_SEAT){}
	virtual void OnFirstPlayerEnter(CPlayerBase &player){}
	virtual void OnLastPlayerLeave(CPlayerBase &player){}
    virtual void OnPlayerSitDown(CPlayerBase &player){}
    virtual void OnBeforePlayerStandUp(CPlayerBase &player){}
    virtual void OnPlayerStandUp(CPlayerBase &player){}
	virtual void OnPlayerReady(CPlayerBase &player){}
	virtual void OnPlayerCancelReady(CPlayerBase &player){}
	virtual void CheckTimeOut(){}
	virtual CRoomBase* Clone(s32 id){ return NULL; }
    virtual void Clean();
    virtual void OnFriendGameDismiss(s32 endstate);
    virtual void OnFriendRoomCreated(const std::string &cfg){}

	s32 Id();
	ERoomState State();
	void SetState(ERoomState state);
	s32 CurPlayerCount();
	s32 CurBeholderCount();
	CPlayerBase* GetPlayerInSeat(s32 seatno);
	CPlayerBase* FindPlayer(u64 userid);
	bool IsAllPlayerReady();
    s32 GetAnte();
    void SetAnte(s32 ante);
    void SetData(const std::string &data){ m_data = data; }
    void SetPasswd(const std::string &passwd){ m_passwd = passwd; };
    void SetName(const std::string &name){ m_name = name; };
    FriendData& GetFriendData() { return m_friendData; }
    s32 FindFreeSeat();
    void ForceAllPlayerReady();
    void DismissFriendRoom(CPlayerBase &player);
    void LeaveFriendRoom(CPlayerBase &player);
    void AgreeDismissFriendRoom(CPlayerBase &player, s32 agree, bool timeout);
    void StartGameFriendRoom(CPlayerBase &player);
    void NotifyFriendRoomInfo(CPlayerBase &player);
    void NotifyFriendRoomDismissProgress(CPlayerBase &player);
	s32 GamingPlayerCount();
    s32 RobotPlayerCount();
	s32 GetPlayerReadyCount();

	virtual s32 CanEnter(CPlayerBase &player, int seatno, const std::string &passwd);
    virtual s32 CanLeave(CPlayerBase &player, s32 reason);
    virtual s32 CanSitDown(CPlayerBase &player, int seatno);
    virtual s32 CanStandUp(CPlayerBase &player);
	virtual s32 CanReady(CPlayerBase &player);
    virtual bool CanChat(CPlayerBase &player, s8 chattype, const std::string &chatcontent, s8 anonymous, std::vector<u64> &receiver);
    virtual bool CanSetRoomAnte(CPlayerBase &player, int ante);
    virtual s32 CanKickOut(CPlayerBase &player, u64 kickuser);
    virtual s32 CanUseInteractItem(CPlayerBase &player, s32 to, s32 item);
    virtual s32 CanStartFriendRoomGame(CPlayerBase &player);
    virtual s32 CanDismissFriendRoom(CPlayerBase &player);

	virtual bool CheckGameStart(bool needAllReady=true);
	virtual void GameEnd(bool needCleanBreakUsers=false);
	virtual void Dissolve(s32 reason=commonproto::E_DissolveReason_Unknown);
    virtual bool CheckFriendGameRoundEnd();
	void PlayerEnter(CPlayerBase &player, int seatno, const std::string &passwd);
	void PlayerLeave(CPlayerBase &player, s32 reason);
    void PlayerSitDown(CPlayerBase &player, int seatno);
    void PlayerStandUp(CPlayerBase &player);
	bool PlayerInRoom(CPlayerBase &player);
	bool PlayerInSeat(CPlayerBase &player);
	bool PlayerIsBeholder(CPlayerBase &player);
	void PlayerReady(CPlayerBase &player);
	void PlayerCancelReady(CPlayerBase &player);
    void PlayerTrusteeShip(CPlayerBase &player);
    void PlayerCancelTrusteeShip(CPlayerBase &player);
    void PlayerRoomChat(CPlayerBase &player, s8 chattype, const std::string &chatcontent, s8 anonymous, std::vector<u64> &receiver, s8 isend, std::vector<std::string> &param);
    void PlayerSetAnte(CPlayerBase &player, s32 ante);
    void KickOutRoom(CPlayerBase &player, u64 kickuserid);
    void UseInteractItem(CPlayerBase &player, s32 to, s32 item);
    bool PlayerResetSeat(CPlayerBase &player, s32 seatno);

	void BroadcastMsg(s32 msgid, const IMessage &msg, bool tobeholder=true);
	void BroadcastMsg(s32 msgid, const IMessage &msg, u64 excludePlayer, bool tobeholder=true);
    void BroadcastMsg2Beholder(s32 msgid, const IMessage &msg);
    void Broadcast2Robots(s32 msgid, const IMessage &msg);

    void CheckActionTimeOut(u64 now);
    void CheckMoreTimeOut(u64 now);
	void CleanBreakUsers();
	void KickOutPlayer(CPlayerBase &player, s32 reason);
    void NotifyRoomBasicInfos(CPlayerBase &player);
    void DumpBasicInfo(commonproto::RoomBasicInfo &info);
    void DumpAllSeatPlayers(std::vector<CPlayerBase*> &players, std::vector<char> &isready);
    void DumpAllBeholderPlayers(std::vector<CPlayerBase*> &players);
	s64 GetGameStartTime() {return m_gameStarttime;}
    void NotifyUserLocationInfo(CPlayerBase *player=NULL);
	bool CreaterInRoom();

private:
    void _GameEndCheckActivity();
    void _ClearAllAgreeDismissAction();
    void _DumpAllBreakPlayers(std::vector<CPlayerBase*> &players, bool all = false);
    void _CleanBreakPlayers(std::vector<CPlayerBase*> &players);
    void _CheckFriendRoomExpire(u64 now);
    void _logBreakPlayersGameEnd(std::vector<CPlayerBase*> &players);

protected:
	// 房间id
	s32 m_id;
	// 座位中的玩家
	CPlayerBase **m_players;
	// 在座位中的玩家个数
	s32 m_curPlayerCount;
	// 房间状态
	ERoomState m_state;
	// 旁观玩家
	std::map<u64, CPlayerBase*> m_beholder;
    // 房间底注
    s32 m_ante;
    // 创建房间时的数据，一般时房间名称
    std::string m_data;
    std::string m_passwd;
    std::string m_name;

    FriendData m_friendData;
	// 游戏开始时间
	u64	m_gameStarttime;
};

#endif
